﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionToWhere
{
    /// <summary>
    /// worker.Id==id中用来提取id的值、worker.Id==temp.Id中用来提取temp.Id的值、worker.CreateDate==DateTime.Now中用来提取DateTime.Now的值
    /// </summary>
    internal class ConstantMemberExpressionVisitor : ConstantExpressionVisitor
    {
        protected override Expression VisitMember(MemberExpression node)
        {
            if(node.Expression == null)
            {
                HandleStaticMember(node);
            }
            else
            {
                HandleInstanceMember(node);
            }
            return node;
        }

        /// <summary>
        /// worker.Id==id中用来提取id的值、worker.Id==temp.Id中用来提取temp.Id的值
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private void HandleInstanceMember(MemberExpression node)
        {
            var visitor = new ConstantMemberExpressionVisitor();
            visitor.Visit(node.Expression);
            Type type = visitor.Value.GetType();
            switch (node.Member.MemberType)
            {
                case MemberTypes.Field:
                    FieldInfo fieldInfo = type.GetField(node.Member.Name);
                    Value = fieldInfo.GetValue(visitor.Value);
                    break;
                case MemberTypes.Property:
                    PropertyInfo propertyInfo = type.GetProperty(node.Member.Name);
                    Value = propertyInfo.GetValue(visitor.Value);
                    break;
                default:
                    throw new NotSupportedException($"Unknow MemberExpression: MemberType={node.Member.MemberType} node.ToString()={node.ToString()}");
            }
        }

        /// <summary>
        /// worker.CreateDate==DateTime.Now中用来提取DateTime.Now的值
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private void HandleStaticMember(MemberExpression node)
        {
            if(node.Member.MemberType == MemberTypes.Field)
            {
                Type type = node.Member.DeclaringType;
                string typeFullName = type.FullName;
                FieldInfo fieldInfo = node.Member.DeclaringType.GetField(node.Member.Name);
                Value = fieldInfo.GetValue(type.Assembly.CreateInstance(typeFullName));
            }
            else if(node.Member.MemberType == MemberTypes.Property)
            {
                Type type = node.Member.DeclaringType;
                string typeFullName = type.FullName;
                PropertyInfo propertyInfo = type.GetProperty(node.Member.Name);
                Value = propertyInfo.GetValue(type.Assembly.CreateInstance(typeFullName));
            }
            else
            {
                throw new NotSupportedException($"Unknow MemberExpression: MemberType={node.Member.MemberType} node.ToString()={node.ToString()}");
            }
        }
    }
}
